﻿using UnityEngine;
using System;
using System.Reflection;
using System.Reflection.Extension;
using System.Extension;
using System.Xml.Serialization;
using System.IO;
using System.Text;

public enum AssetDomain { FileSystem, ResourceBundle, RemoteServer, SDKBundle}

public class Synchronise : Attribute 
{
    public string ResourcePath { get; set; }
    public string CatchPath { get; set; }
    public string DocumentPath { get; set; }
    public string StreamingPath { get; set; }
    public string SDKPath { get; set; }
    public string URL { get; set; }

    string catchAssetPath { get { return Application.temporaryCachePath + CatchPath; } }
    string documentAssetPath { get { return Application.persistentDataPath + DocumentPath; } }
    string streamingAssetPath { get { return Application.streamingAssetsPath + StreamingPath; } }
    string sdkAssetPath { get { return SDKPath +".xml"; } }

    public object GetObject(string path, Type type, AssetDomain location)
    {
        
        object result = null;
        XmlSerializer serializer = new XmlSerializer(type);
        if (location == AssetDomain.SDKBundle)
        {
#if WRB_HIGHSTAKES
            string xmlData = Utility.GetFileData(path);
            using (Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(xmlData)))
                result = serializer.Deserialize(stream);
#endif
        }
        else if (location == AssetDomain.ResourceBundle)
        {
            TextAsset xmlAsset = Resources.Load<TextAsset>(ResourcePath);
            if (xmlAsset.isNotNull())
            using (Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(xmlAsset.text)))
                result = serializer.Deserialize(stream);
        }
        else if(location == AssetDomain.FileSystem)
            using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
                result = serializer.Deserialize(stream);
        //else if(location == AssetDomain.Server)   // Server Loading goes here;
        return result;
    }

    void SaveObject(object value,string path, Type type)
    {
        if (path.isNotEmpty())
        {
            XmlSerializer serializer = new XmlSerializer(type);
            using (TextWriter writer = new StreamWriter(path))
                serializer.Serialize(writer, value);
        }
    }

    public void Load(object source, MemberInfo memberInfo)  
    {
        Type memberType = memberInfo.GetMemberType();
        AssetDomain location = AssetDomain.FileSystem;
        string path = GetAssetPath(ref location);
        if (path.isNotEmpty())
        {
            object value = GetObject(path, memberType, location);
            
            //persist value here
            if (value.isNotNull())
            {
                //if(catchAssetPath.isResourceExists())
                //{
                //    object objectCatch = GetObject(catchAssetPath, memberType, AssetDomain.FileSystem);
                //    if (objectCatch.isNotNull())
                //        value.Presist(objectCatch);
                //}
                memberInfo.SetValue(source, value);
            }
               
        }
    }

    public void Catch(object source, MemberInfo memberInfo)
    {
        Type memberType = memberInfo.GetMemberType();
        object value = memberInfo.GetValue(source);
        if(CatchPath.isNotEmpty() && value.isNotNull())
            SaveObject(value, catchAssetPath, memberType);
    }

    private string GetAssetPath(ref AssetDomain location)
    {
        string path = null;
        location = AssetDomain.FileSystem;
        if (SDKPath.isNotEmpty())
        { path = sdkAssetPath; location = AssetDomain.SDKBundle; }
        else if (streamingAssetPath.isResourceExists())
            path = streamingAssetPath;
        else if (ResourcePath.isNotEmpty())
        { path = ResourcePath; location = AssetDomain.ResourceBundle; }
        else if (catchAssetPath.isResourceExists())
            path = catchAssetPath;
        else if (URL.isNotEmpty())
        { path = URL; location = AssetDomain.RemoteServer; }
        return path;
    }
    public static void SaveAsXML<T>(T t, string path)
    {
        if (t.isNotNull() && path.isNotEmpty())
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (TextWriter writer = new StreamWriter(path))
                serializer.Serialize(writer, t);
        }
    }

    public static void SaveAsXML(object obj, Type type , string path)
    {
        if (obj.isNotNull() && path.isNotEmpty())
        {
            //Debug.Log("TYpe : " + type.FullName);
            XmlSerializer serializer = new XmlSerializer(type);
            using (TextWriter writer = new StreamWriter(path))
                serializer.Serialize(writer, obj);
        }
    }
}

/*
 
 
    public object GetObject(Type type)
    {
        object result = null;
        XmlSerializer serializer = new XmlSerializer(type);
        using (Stream stream = GetContentStream())
        {
            if (stream != null)
                result = serializer.Deserialize(GetContentStream());
            else
                Debug.LogWarning("Asset Not Found : " + ResourcePath + DocumentPath + CatchPath + StreamingAssetPath);
        }
        return result;
    }

    Stream GetContentStream()
    {
        Stream result = null;
        if (ResourcePath.isNotEmpty())
        {
            TextAsset xmlAsset = Resources.Load<TextAsset>(ResourcePath);
            if (xmlAsset)
                result = new MemoryStream(ASCIIEncoding.Default.GetBytes(xmlAsset.text));
        }
        else if (DocumentPath.isNotEmpty())
            result = new FileStream(Application.persistentDataPath + DocumentPath, FileMode.Open, FileAccess.Read);
        else if (CatchPath.isNotEmpty())
            result = new FileStream(Application.temporaryCachePath + CatchPath, FileMode.Open, FileAccess.Read);
        else if (StreamingAssetPath.isNotEmpty())
            result = new FileStream(Application.streamingAssetsPath + StreamingAssetPath, FileMode.Open, FileAccess.Read);
        return result;
    }

    public static void SaveAsXML<T>(T t, string path)
    {
        if(t.isNotNull() && path.isNotEmpty())
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (TextWriter writer = new StreamWriter(path))
                serializer.Serialize(writer, t);
        }
    }

    public static T LoadFromXML<T>( string path)
    {
        T result = default(T);
        if(path.isNotEmpty())
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            using (TextReader reader = new StreamReader(path))
                result = (T)serializer.Deserialize(reader);
        }
        return result;
    }
 
 */
